# encoding: utf8
import simplejson as json
import logging

from django.http import JsonResponse
from django.views.generic import View
from schema import SchemaError
from simplejson import JSONDecodeError

from common import constants
from storage.models import VendorProduct
from storage.util_schema import product_post_schema, product_patch_schema

logger = logging.getLogger('storage')


class ProductListView(View):
    def get(self, request, *args, **kwargs):
        """
        查询商品

        /products_list/?bar_code=**code1**,**code2**,**code3**

        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        logger.info(str(request))
        bar_code_param = request.GET.get('bar_code')
        if not bar_code_param:
            return JsonResponse(
                data={
                    'message': constants.MESSAGE_MISSING,
                    'errors': [
                        {
                            'code': 'argument {argument} missing'.format(argument='bar_code'),
                            'field': 'bar_code',
                            'resource': 'VendorProduct'
                        }
                    ]
                },
                status=400)

        bar_code_list = bar_code_param.split(',')

        product_list = VendorProduct.objects.filter(bar_code__in=bar_code_list)

        json_data = [
            {
                'bar_code': product.bar_code,
                'name': product.name,
                'vendor_name': product.vendor_name,
                'brand': product.brand,
                'ware_id': product.ware_id,
                'packing': product.packing,
                'region': product.region,
                'weight': product.weight,
                'tax_rate': product.tax_rate,
                'seo_info': product.seo_info,
                'properties': product.properties
            } for product in product_list]

        return JsonResponse(json_data, safe=False)


class ProductView(View):
    def post(self, request, *args, **kwargs):
        """
        创建商品

        /products/**bar_code**/
        **bar_code**必填

        :param request:
        :param args:
        :param kwargs:
        :return:
        """

        try:
            request_body_data = request.body.decode('utf-8')
            post_data = json.loads(request_body_data)

            validate_product = product_post_schema.validate(post_data)

            bar_code = validate_product.get('bar_code')
            if VendorProduct.objects.filter(bar_code=bar_code).exists():
                return JsonResponse(
                    data={
                        'message': constants.MESSAGE_ALREADY_EXISTS,
                        'errors': [
                            {
                                'code': constants.ERROR_CODE_ALREADY_EXISTS,
                                'resource': 'VendorProduct'
                            }
                        ]
                    },
                    status=422)

            VendorProduct(**validate_product).save()
            return JsonResponse(data=validate_product)

        except JSONDecodeError as json_error:
            logger.exception(json_error)
            return JsonResponse(
                data={
                    'message': constants.MESSAGE_PARSING_ERROR
                },
                status=400)

        except SchemaError as schema_error:
            logger.exception(schema_error)
            return JsonResponse(
                data={
                    'message': constants.MESSAGE_VALIDATE_ERROR,
                    'errors': [
                        {
                            'code': schema_error.code,
                            'field': 'schema',
                            'resource': 'VendorProduct'
                        }
                    ]
                },
                status=422)

    def patch(self, request, *args, **kwargs):
        """
        更新商品

        /products/**bar_code**/
        **bar_code**必填

        :param request:
        :param args:
        :param kwargs:
        :return:
        """
        bar_code = kwargs.get('bar_code')

        if not VendorProduct.objects.filter(bar_code=bar_code).exists():
            return JsonResponse(
                data={
                    'message': constants.MESSAGE_MISSING,
                    'errors': [
                        {
                            'code': constants.ERROR_CODE_MISSING,
                            'resource': 'VendorProduct'
                        }
                    ]
                },
                status=422)

        try:
            request_body_data = request.body.decode('utf-8')
            post_data = json.loads(request_body_data)
            validate_product = product_patch_schema.validate(post_data)
            VendorProduct.objects.filter(bar_code=bar_code).update(**validate_product)
            product = VendorProduct.objects.get(bar_code=bar_code)
            json_data = {
                'bar_code': product.bar_code,
                'name': product.name,
                'vendor_name': product.vendor_name,
                'brand': product.brand,
                'ware_id': product.ware_id,
                'packing': product.packing,
                'region': product.region,
                'weight': product.weight,
                'tax_rate': product.tax_rate,
                'seo_info': product.seo_info,
                'properties': product.properties
            }

            return JsonResponse(json_data)

        except JSONDecodeError as json_error:
            logger.exception(json_error)
            return JsonResponse(
                data={
                    'message': constants.MESSAGE_PARSING_ERROR
                },
                status=400)

        except SchemaError as schema_error:
            logger.exception(schema_error)
            return JsonResponse(
                data={
                    'message': constants.MESSAGE_VALIDATE_ERROR,
                    'errors': [
                        {
                            'code': schema_error.code,
                            'field': 'schema',
                            'resource': 'VendorProduct'
                        }
                    ]
                },
                status=422)
